home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Workbench Add-On
/
Workbench Add-On - Volume 1.iso
/
BBS-Archive
/
Comm
/
term-source.lha
/
Extras
/
Source
/
term-Source.lha
/
CustomRequest.c
< prev
next >
Wrap
C/C++ Source or Header
|
1995-02-06
|
19KB
|
839 lines
/*
** CustomRequest.c
**
** EasyRequest like custom requester
**
** Copyright © 1990-1995 by Olaf `Olsen' Barthel
** All Rights Reserved
*/
#include "termGlobal.h"
/* Pack two words into a long. */
#define PACK_ULONG(a,b) (((ULONG)(a)) << 16 | b)
/* Gadget extension. */
struct ButtonInfo
{
struct Image *ButtonImage;
UWORD LabelLen,
LabelLeft,
LabelTop;
};
/* GetScreenInfo():
*
* Obtain the currently visible screen area.
*/
STATIC VOID __regargs
GetScreenInfo(struct Screen *Screen,WORD *Left,WORD *Top,WORD *Width,WORD *Height)
{
struct ViewPortExtra *Extra;
struct TagItem Tags[2] = { VTAG_VIEWPORTEXTRA_GET, NULL, TAG_DONE };
if(!VideoControl(Screen -> ViewPort . ColorMap,Tags))
Extra = (struct ViewPortExtra *)Tags[0] . ti_Data;
else
Extra = NULL;
if(!Extra)
Extra = Screen -> ViewPort . ColorMap -> cm_vpe;
if(!Extra)
Extra = (struct ViewPortExtra *)GfxLookUp(&Screen -> ViewPort);
if(Extra)
{
struct Rectangle Clip;
QueryOverscan(GetVPModeID(&Screen -> ViewPort),&Clip,OSCAN_TEXT);
*Width = Extra -> DisplayClip . MaxX - Extra -> DisplayClip . MinX + 1;
*Height = Extra -> DisplayClip . MaxY - Extra -> DisplayClip . MinY + 1;
if(*Width < Clip . MaxX - Clip . MinX + 1)
*Width = Clip . MaxX - Clip . MinX + 1;
if(*Height < Clip . MaxY - Clip . MinY + 1)
*Height = Clip . MaxY - Clip . MinY + 1;
}
else
{
*Width = Screen -> Width;
*Height = Screen -> Height;
}
*Left = ABS(Screen -> LeftEdge);
*Top = ABS(Screen -> TopEdge);
if(*Left > Screen -> Width || *Left < 0)
*Left = 0;
if(*Top > Screen -> Height || *Top < 0)
*Top = 0;
}
/* CentreWindow():
*
* Centre a window within the visible bounds of
* a screen.
*/
STATIC VOID __regargs
CentreWindow(struct Screen *Screen,WORD Width,WORD Height,WORD *Left,WORD *Top)
{
WORD ScreenWidth,ScreenHeight,ScreenLeft,ScreenTop;
GetScreenInfo(Screen,&ScreenLeft,&ScreenTop,&ScreenWidth,&ScreenHeight);
*Left = ScreenLeft + (ScreenWidth - Width) / 2;
*Top = ScreenTop + (ScreenHeight - Height) / 2;
}
/* RenderText():
*
* Render the button text.
*/
STATIC VOID __regargs
RenderText(struct RastPort *RPort,struct GadgetInfo *GadgetInfo,struct Gadget *Gadget,struct ButtonInfo *ButtonInfo)
{
STRPTR Label = (STRPTR)Gadget -> GadgetText;
ULONG State;
UWORD Pen;
/* Which state is the button in? */
if(Gadget -> Flags & GFLG_SELECTED)
{
State = IDS_SELECTED;
Pen = GadgetInfo -> gi_DrInfo -> dri_Pens[FILLTEXTPEN];
}
else
{
State = IDS_NORMAL;
Pen = GadgetInfo -> gi_DrInfo -> dri_Pens[TEXTPEN];
}
/* Render the frame. */
DoMethod(Gadget -> GadgetRender,IM_DRAWFRAME,RPort,PACK_ULONG(Gadget -> LeftEdge,Gadget -> TopEdge),State,GadgetInfo -> gi_DrInfo,PACK_ULONG(Gadget -> Width,Gadget -> Height));
/* Set the rendering pens. */
if(IntuitionBase -> LibNode . lib_Version >= 39)
SetABPenDrMd(RPort,Pen,0,JAM1);
else
{
SetDrMd(RPort,JAM1);
SetAPen(RPort,Pen);
}
/* Render the button label. */
Move(RPort,Gadget -> LeftEdge + ButtonInfo -> LabelLeft,Gadget -> TopEdge + ButtonInfo -> LabelTop);
Text(RPort,Label,ButtonInfo -> LabelLen);
}
/* RenderButton():
*
* Render the button label.
*/
STATIC ULONG __regargs
RenderButton(struct IClass *class,Object *object,struct gpRender *RenderInfo)
{
RenderText(RenderInfo -> gpr_RPort,RenderInfo -> gpr_GInfo,(struct Gadget *)object,INST_DATA(class,object));
return(TRUE);
}
/* FreeButton():
*
* Free a button gadget object.
*/
STATIC ULONG __regargs
FreeButton(struct IClass *class,Object *object,Msg msg)
{
struct ButtonInfo *ButtonInfo = INST_DATA(class,object);
if(ButtonInfo -> ButtonImage)
DisposeObject(ButtonInfo -> ButtonImage);
return(DoSuperMethodA(class,object,msg));
}
/* NewButton():
*
* Create a new button object.
*/
STATIC ULONG __regargs
NewButton(struct IClass *class,Object *object,struct opSet *SetMethod)
{
struct TagItem *Tag,*TagList;
struct Gadget *NewGadget = NULL;
struct DrawInfo *DrawInfo = NULL;
STRPTR Label = NULL;
TagList = SetMethod -> ops_AttrList;
while(Tag = NextTagItem(&TagList))
{
switch(Tag -> ti_Tag)
{
case GA_Text:
Label = (STRPTR)Tag -> ti_Data;
break;
case GA_DrawInfo:
DrawInfo = (struct DrawInfo *)Tag -> ti_Data;
break;
}
}
if(Label && DrawInfo)
{
struct RastPort __aligned RastPort;
UWORD Width,Height,LabelWidth,LabelHeight,LabelLen;
LabelLen = strlen(Label);
InitRastPort(&RastPort);
SetFont(&RastPort,DrawInfo -> dri_Font);
LabelWidth = TextLength(&RastPort,Label,LabelLen);
LabelHeight = RastPort . TxHeight;
Width = 2 + LabelWidth + (6 * RastPort . TxWidth) / 2;
Height = 2 + LabelHeight + RastPort . TxHeight / 2;
if(Width && Height)
{
struct Image *ButtonImage;
/* Create a button frame. */
if(ButtonImage = NewObject(NULL,"frameiclass",
IA_Width, Width,
IA_Height, Height,
TAG_DONE))
{
struct TagItem *OldTags = SetMethod -> ops_AttrList,
NewTags[4];
/* Add new tag values. */
NewTags[0] . ti_Tag = GA_Image;
NewTags[0] . ti_Data = (ULONG)ButtonImage;
NewTags[1] . ti_Tag = GA_Width;
NewTags[1] . ti_Data = (ULONG)Width;
NewTags[2] . ti_Tag = GA_Height;
NewTags[2] . ti_Data = (ULONG)Height;
NewTags[3] . ti_Tag = TAG_MORE;
NewTags[3] . ti_Data = (ULONG)OldTags;
SetMethod -> ops_AttrList = NewTags;
/* Create new object. */
if(NewGadget = (struct Gadget *)DoSuperMethodA(class,object,(Msg)SetMethod))
{
struct ButtonInfo *ButtonInfo = INST_DATA(class,NewGadget);
ButtonInfo -> LabelLen = LabelLen;
ButtonInfo -> LabelLeft = (Width - LabelWidth) / 2;
ButtonInfo -> LabelTop = RastPort . TxBaseline + (Height - LabelHeight) / 2;
/* Remember the frame image. */
ButtonInfo -> ButtonImage = ButtonImage;
/* Restore the tags. */
SetMethod -> ops_AttrList = OldTags;
}
else
DisposeObject(ButtonImage);
}
}
}
return((ULONG)NewGadget);
}
/* HandleButton():
*
* Handle button input.
*/
STATIC ULONG __regargs
HandleButton(struct IClass *class,Object *object,struct gpInput *InputInfo)
{
ULONG Result = GMR_MEACTIVE;
BOOL Redraw = FALSE,
Final = FALSE;
struct ButtonInfo *ButtonInfo = INST_DATA(class,object);
struct Gadget *Button = (struct Gadget *)object;
/* Only mouse events trigger actions. */
if(InputInfo -> gpi_IEvent -> ie_Class == IECLASS_RAWMOUSE)
{
/* Selection cancelled or no command available? */
if(InputInfo -> gpi_IEvent -> ie_Code == MENUDOWN)
{
if(Button -> Flags & GFLG_SELECTED)
{
Button -> Flags &= ~GFLG_SELECTED;
Redraw = TRUE;
}
Result = GMR_NOREUSE;
/* No further actions, please. */
Final = TRUE;
}
else
{
/* Select button released? */
if(InputInfo -> gpi_IEvent -> ie_Code == SELECTUP)
{
if(DoMethod((Object *)ButtonInfo -> ButtonImage,IM_HITFRAME,PACK_ULONG(InputInfo -> gpi_Mouse . X,InputInfo -> gpi_Mouse . Y),PACK_ULONG(Button -> Width,Button -> Height)))
{
if(Button -> Flags & GFLG_SELECTED)
{
*InputInfo -> gpi_Termination = 0;
Button -> Flags &= ~GFLG_SELECTED;
Redraw = TRUE;
}
else
*InputInfo -> gpi_Termination = 1;
Result = GMR_REUSE | GMR_VERIFY;
}
else
Result = GMR_NOREUSE;
/* No further actions, please. */
Final = TRUE;
}
}
}
/* Change highlighting mode? */
if(!Final)
{
/* Hit inside the boundaries? */
if(DoMethod((Object *)ButtonInfo -> ButtonImage,IM_HITFRAME,PACK_ULONG(InputInfo -> gpi_Mouse . X,InputInfo -> gpi_Mouse . Y),PACK_ULONG(Button -> Width,Button -> Height)))
{
if(!(Button -> Flags & GFLG_SELECTED))
{
Button -> Flags |= GFLG_SELECTED;
Redraw = TRUE;
}
}
else
{
if(Button -> Flags & GFLG_SELECTED)
{
Button -> Flags &= ~GFLG_SELECTED;
Redraw = TRUE;
}
}
}
/* Redraw the object? */
if(Redraw)
{
struct RastPort *RPort;
if(RPort = ObtainGIRPort(InputInfo -> gpi_GInfo))
{
RenderText(RPort,InputInfo -> gpi_GInfo,Button,ButtonInfo);
ReleaseGIRPort(RPort);
}
}
return(Result);
}
/* ButtonDispatch():
*
* The button gadget class dispatcher.
*/
STATIC ULONG __saveds __asm
ButtonDispatch(register __a0 struct IClass *class,register __a2 Object *object,register __a1 Msg msg)
{
/* Select the message method. */
switch(msg -> MethodID)
{
case OM_NEW:
return(NewButton(class,object,(struct opSet *)msg));
case OM_DISPOSE:
return(FreeButton(class,object,msg));
case GM_RENDER:
return(RenderButton(class,object,(struct gpRender *)msg));
case GM_HITTEST:
return(GMR_GADGETHIT);
case GM_GOINACTIVE:
return(0);
case GM_GOACTIVE:
return(GMR_MEACTIVE);
case GM_HANDLEINPUT:
return(HandleButton(class,object,(struct gpInput *)msg));
default:
return(DoSuperMethodA(class,object,msg));
}
}
/* DeleteButtonClass(VOID):
*
* Free private button gadget class.
*/
STATIC VOID __regargs
DeleteButtonClass(Class *ButtonClass)
{
if(ButtonClass)
FreeClass(ButtonClass);
}
/* CreateButtonClass(VOID):
*
* Create private button gadget class.
*/
STATIC Class *
CreateButtonClass(VOID)
{
Class *ButtonClass;
if(ButtonClass = MakeClass(NULL,GADGETCLASS,NULL,sizeof(struct ButtonInfo),0))
{
ButtonClass -> cl_Dispatcher . h_Entry = (HOOKFUNC)ButtonDispatch;
return(ButtonClass);
}
else
return(NULL);
}
/* DrawDent():
*
* Draw a recessed box.
*/
STATIC VOID __regargs
DrawDent(struct RastPort *RPort,struct DrawInfo *DrawInfo,LONG Left,LONG Top,LONG Width,LONG Height)
{
SetAPen(RPort,DrawInfo -> dri_Pens[BACKGROUNDPEN]);
RectFill(RPort,Left + 2,Top + 1,Left + Width - 3,Top + Height - 2);
SetAPen(RPort,DrawInfo -> dri_Pens[SHADOWPEN]);
Move(RPort,Left + 1,Top + 1);
Draw(RPort,Left + 1,Top + Height - 1);
Draw(RPort,Left,Top + Height - 1);
Draw(RPort,Left,Top);
Draw(RPort,Left + Width - 2,Top);
SetAPen(RPort,DrawInfo -> dri_Pens[SHINEPEN]);
Move(RPort,Left + 1,Top + Height - 1);
Draw(RPort,Left + Width - 1,Top + Height - 1);
Draw(RPort,Left + Width - 1,Top);
Draw(RPort,Left + Width - 2,Top + 1);
Draw(RPort,Left + Width - 2,Top + Height - 2);
}
STATIC VOID
StuffChar(VOID)
{
__emit(0x16C0); /* MOVE D0,(A3)+ */
}
STATIC VOID __asm
CountChar(register __a3 LONG *Count,register __d0 UBYTE Char)
{
if(Char == '\n' || Char == '\0')
Count[1]++;
Count[0]++;
}
/* ShowInfo():
*
* Display an EasyRequest like information requester.
*/
VOID __stdargs
ShowInfo(struct Window *Parent,STRPTR Title,STRPTR Continue,STRPTR FormatString,...)
{
struct Screen *Screen,
*OldFrontScreen;
ULONG IntuiLock;
if(Parent)
Screen = Parent -> WScreen;
else
Screen = LockPubScreen(NULL);
IntuiLock = LockIBase(NULL);
if((OldFrontScreen = IntuitionBase -> FirstScreen) == Screen)
OldFrontScreen = NULL;
UnlockIBase(IntuiLock);
if(Screen)
{
struct DrawInfo *DrawInfo;
if(OldFrontScreen)
ScreenToFront(Screen);
if(DrawInfo = GetScreenDrawInfo(Screen))
{
Class *ButtonClass;
if(ButtonClass = CreateButtonClass())
{
struct Gadget *Button;
if(Button = NewObject(ButtonClass,NULL,
GA_Text, Continue,
GA_DrawInfo, DrawInfo,
GA_RelVerify, TRUE,
TAG_DONE))
{
va_list VarArgs;
LONG Information[2];
STRPTR Data;
Information[0] = Information[1] = 0;
va_start(VarArgs,FormatString);
RawDoFmt(FormatString,VarArgs,(VOID (*)())CountChar,Information);
va_end(VarArgs);
if(Data = (STRPTR)AllocVec(Information[0],MEMF_ANY))
{
LONG i,Lines = Information[1],Start,Len;
WORD Width = 0,Height,Left,Top;
struct IntuiText IText;
struct Window *Window;
struct TextFont *Font = DrawInfo -> dri_Font;
WORD WindowLeft,WindowTop,
WindowWidth,WindowHeight,
ScreenWidth,ScreenHeight,
ScreenLeft,ScreenTop;
va_start(VarArgs,FormatString);
RawDoFmt(FormatString,VarArgs,(VOID (*)())StuffChar,Data);
va_end(VarArgs);
memset(&IText,0,sizeof(struct IntuiText));
IText . ITextFont = Screen -> Font;
for(i = Start = 0 ; i < Information[0] ; i++)
{
if(!Data[i])
{
IText . IText = &Data[Start];
if((Len = IntuiTextLength(&IText)) > Width)
Width = Len;
Start = i + 1;
}
else
{
if(Data[i] == '\n')
{
if(Start != i)
{
Data[i] = 0;
IText . IText = &Data[Start];
Len = IntuiTextLength(&IText);
Data[i] = '\n';
if(Len > Width)
Width = Len;
}
Start = i + 1;
}
}
}
Len = Button -> Width + 2 * Font -> tf_XSize;
if(Width < Len)
Width = Len;
Width = Screen -> WBorLeft + 4 + 3 * Font -> tf_XSize + Width + Screen -> WBorRight;
Height = Screen -> WBorTop + Screen -> Font -> ta_YSize + 1 + Font -> tf_YSize / 2 + (2 + Lines) * Font -> tf_YSize + Button -> Height + Screen -> WBorBottom;
if(Parent)
{
WindowLeft = Parent -> LeftEdge + Parent -> BorderLeft;
WindowTop = Parent -> TopEdge + Parent -> BorderTop;
WindowWidth = Parent -> Width - (Parent -> BorderLeft + Parent -> BorderRight);
WindowHeight = Parent -> Height - (Parent ->BorderTop + Parent -> BorderBottom);
if((Left = WindowLeft + (WindowWidth - Width) / 2) < 0)
Left = 0;
if((Top = WindowTop + (WindowHeight - Height) / 2) < 0)
Top = 0;
GetScreenInfo(Screen,&ScreenLeft,&ScreenTop,&ScreenWidth,&ScreenHeight);
if(Left < ScreenLeft || Left + Width > ScreenLeft + ScreenWidth)
Left = -1;
if(Top < ScreenTop || Top + Height > ScreenTop + ScreenHeight)
Top = -1;
if(Top == -1 || Left == -1)
CentreWindow(Screen,Width,Height,&Left,&Top);
}
else
CentreWindow(Screen,Width,Height,&Left,&Top);
if(Window = OpenWindowTags(NULL,
WA_Left, Left,
WA_Top, Top,
WA_Width, Width,
WA_Height, Height,
WA_Title, Title,
WA_DragBar, TRUE,
WA_DepthGadget, TRUE,
WA_RMBTrap, TRUE,
WA_IDCMP, IDCMP_GADGETUP | IDCMP_VANILLAKEY | IDCMP_RAWKEY,
WA_Activate, TRUE,
WA_CustomScreen,Screen,
TAG_DONE))
{
struct IntuiMessage *Message;
struct RastPort *RPort = Window -> RPort;
BOOL Terminated = FALSE,
KeyHit = FALSE;
if(GfxBase -> LibNode . lib_Version >= 39)
{
LONG MaxPen = 0;
for(i = 0 ; i < DrawInfo -> dri_NumPens ; i++)
{
if(DrawInfo -> dri_Pens[i] > MaxPen)
MaxPen = DrawInfo -> dri_Pens[i];
}
SetMaxPen(Window -> RPort,MaxPen);
}
SetFont(RPort,Font);
if(GfxBase -> LibNode . lib_Version >= 39)
SetABPenDrMd(RPort,DrawInfo -> dri_Pens[SHINEPEN],DrawInfo -> dri_Pens[BACKGROUNDPEN],JAM2);
else
{
SetAPen(RPort,DrawInfo -> dri_Pens[SHINEPEN]);
SetBPen(RPort,DrawInfo -> dri_Pens[BACKGROUNDPEN]);
SetDrMd(RPort,JAM2);
}
LockLayerRom(Window -> RPort -> Layer);
SetAfPt(RPort,(UWORD *)&Crosshatch,1);
RectFill(RPort,Window -> BorderLeft,Window -> BorderTop,Window -> Width - (Window -> BorderRight + 1),Window -> Height - (Window -> BorderBottom + 1));
SetAfPt(RPort,NULL,0);
Left = Window -> BorderLeft + RPort -> Font -> tf_XSize;
Top = Window -> BorderTop + RPort -> Font -> tf_YSize / 2;
Width = Window -> Width - (Window -> BorderRight + 2 * RPort -> Font -> tf_XSize + Window -> BorderLeft);
Height = (1 + Lines) * RPort -> Font -> tf_YSize;
SetDrMd(RPort,JAM1);
DrawDent(RPort,DrawInfo,Left,Top,Width,Height);
SetAttrs(Button,
GA_Left, (Window -> Width - Button -> Width) / 2,
GA_Top, Window -> BorderTop + Font -> tf_YSize / 2 + (1 + Lines) * Font -> tf_YSize + (Window -> Height - (Window -> BorderTop + Font -> tf_YSize / 2 + (1 + Lines) * Font -> tf_YSize + Window -> BorderBottom) - Button -> Height) / 2,
TAG_DONE);
UnlockLayerRom(Window -> RPort -> Layer);
AddGadget(Window,Button,(UWORD)~0);
RefreshGList(Button,Window,NULL,1);
LockLayerRom(Window -> RPort -> Layer);
SetAPen(RPort,DrawInfo -> dri_Pens[TEXTPEN]);
Top = Window -> BorderTop + Font -> tf_YSize + Font -> tf_Baseline;
for(i = Start = 0 ; i < Information[0] ; i++)
{
if(!Data[i])
{
Move(RPort,(Window -> Width - TextLength(RPort,&Data[Start],strlen(&Data[Start]))) / 2,Top);
Text(RPort,&Data[Start],strlen(&Data[Start]));
Top += Font -> tf_YSize;
}
else
{
if(Data[i] == '\n')
{
if(Start != i)
{
Data[i] = 0;
Move(RPort,(Window -> Width - TextLength(RPort,&Data[Start],strlen(&Data[Start]))) / 2,Top);
Text(RPort,&Data[Start],strlen(&Data[Start]));
}
Top += Font -> tf_YSize;
Start = i + 1;
}
}
}
UnlockLayerRom(Window -> RPort -> Layer);
do
{
WaitPort(Window -> UserPort);
while(Message = (struct IntuiMessage *)GetMsg(Window -> UserPort))
{
if(Message -> Class == IDCMP_GADGETUP)
Terminated = TRUE;
if(Message -> Class == IDCMP_VANILLAKEY)
{
if(Message -> Code == '\33' || Message -> Code == '\r')
KeyHit = Terminated = TRUE;
}
if(Message -> Class == IDCMP_RAWKEY)
{
UWORD Code = Message -> Code;
ReplyMsg((struct Message *)Message);
if(Code == HELP_CODE)
GuideDisplay(CONTEXT_MAIN);
}
else
ReplyMsg((struct Message *)Message);
}
}
while(!Terminated);
if(KeyHit)
{
SetAttrs(Button,GA_Selected,TRUE,TAG_DONE);
RefreshGList(Button,Window,NULL,1);
WaitTime(0,80000);
SetAttrs(Button,GA_Selected,FALSE,TAG_DONE);
RefreshGList(Button,Window,NULL,1);
}
CloseWindow(Window);
}
FreeVec(Data);
}
DisposeObject(Button);
}
DeleteButtonClass(ButtonClass);
}
FreeScreenDrawInfo(Screen,DrawInfo);
}
if(!Parent)
UnlockPubScreen(NULL,Screen);
}
if(OldFrontScreen)
{
struct Screen *NewFrontScreen = NULL,*Screen;
Forbid();
IntuiLock = LockIBase(NULL);
Screen = IntuitionBase -> FirstScreen;
while(Screen)
{
if(Screen == OldFrontScreen)
{
NewFrontScreen = Screen;
break;
}
else
Screen = Screen -> NextScreen;
}
UnlockIBase(IntuiLock);
if(NewFrontScreen)
ScreenToFront(NewFrontScreen);
Permit();
}
}